package service

import (
	__ "ai_srv/basic/aiproto"
	"ai_srv/basic/config"
	"ai_srv/handler/dao"
	"context"
	"time"
)

type Server struct {
	__.UnimplementedAiServer
}

// ChatWithAI 实现 gRPC 方法：支持多轮对话的 KimiAI 调用
//
// 功能特性：
// - 智能会话管理：自动创建新会话或继续现有会话
// - 上下文理解：维护最近10轮对话历史，确保AI理解对话上下文
// - 天气查询集成：自动识别天气查询请求，提供专业天气信息
// - 数据持久化：所有对话记录自动保存，支持历史回顾
// - 错误处理：完善的错误处理机制，确保服务稳定性
//
// 参数:
//   - ctx: gRPC上下文，用于请求超时控制
//   - in: 包含用户ID、会话ID和用户消息的请求
//   - user_id: 用户唯一标识
//   - session_id: 会话ID，为空则创建新会话，否则继续现有会话
//   - message: 用户输入的消息内容
//
// 返回:
//   - *__.ChatWithAIResp: 包含AI回复和会话ID的响应
//   - ChatWithAI: AI生成的回复内容
//   - session_id: 会话ID，用于后续多轮对话的上下文维护
//   - error: 错误信息，包含详细的错误描述
func (s *Server) ChatWithAI(_ context.Context, in *__.ChatWithAIReq) (*__.ChatWithAIResp, error) {
	// 调用核心对话处理函数
	// 该函数会完成以下操作：
	// 1. 会话管理：获取或创建会话
	// 2. 历史上下文：构建最近10轮对话历史
	// 3. 智能识别：判断是否为天气查询
	// 4. AI调用：调用Kimi API获取回复
	// 5. 数据保存：将对话记录保存到数据库
	aiText, sessionId, err := dao.ChatWithKimi(config.Ctx, in.GetUserId(), in.GetSessionId(), in.GetMessage())
	if err != nil {
		// 返回详细错误信息，便于客户端处理
		return nil, err
	}

	// 构建成功响应
	// 会话ID是多轮对话的关键，客户端应保存此ID用于后续对话
	return &__.ChatWithAIResp{
		ChatWithAI: aiText,
		SessionId:  sessionId,
	}, nil
}

// GetHistory 返回指定用户或会话的对话记录
//
// 功能特性：
// - 灵活查询：支持按用户或特定会话查询历史记录
// - 分页支持：通过limit参数控制返回记录数量
// - 时间排序：按创建时间升序排列，确保对话顺序正确
// - 格式统一：返回标准化的历史记录格式
//
// 参数:
//   - ctx: gRPC上下文，用于数据库操作超时控制
//   - in: 包含查询条件的请求
//   - user_id: 用户ID，必填
//   - session_id: 会话ID，为空则查询用户所有对话，否则只查询指定会话
//   - limit: 返回条数限制，默认10条，最大100条
//
// 返回:
//   - *__.GetHistoryResp: 包含历史对话记录的响应
//   - items: 历史记录列表，每条记录包含用户消息、AI回复和创建时间
//   - error: 错误信息，包含详细的错误描述
func (s *Server) GetHistory(_ context.Context, in *__.GetHistoryReq) (*__.GetHistoryResp, error) {
	// 从数据库查询历史对话记录
	// 支持按用户ID和会话ID进行精确查询
	items, err := dao.GetHistory(config.Ctx, in.GetUserId(), in.GetSessionId(), in.GetLimit())
	if err != nil {
		// 数据库查询失败，返回错误信息
		return nil, err
	}

	// 构建响应，将数据库记录转换为protobuf格式
	// 确保时间格式统一使用ISO8601标准
	resp := &__.GetHistoryResp{}
	for _, it := range items {
		resp.Items = append(resp.Items, &__.HistoryItem{
			UserMessage: it.UserMessage,
			AiMessage:   it.AiMessage,
			CreatedAt:   it.CreatedAt.Format(time.RFC3339), // 使用ISO8601格式，便于前端解析
		})
	}
	return resp, nil
}

// GetSessionList 返回用户的会话列表
//
// 功能特性：
// - 会话管理：显示用户的所有历史会话
// - 智能排序：按更新时间倒序排列，最新会话在前
// - 分页支持：通过limit参数控制返回会话数量
// - 会话信息：包含会话ID、标题、创建和更新时间
// - 快速访问：用户可快速选择继续某个会话进行多轮对话
//
// 参数:
//   - ctx: gRPC上下文，用于数据库操作超时控制
//   - in: 包含查询条件的请求
//   - user_id: 用户ID，必填
//   - limit: 返回条数限制，默认20条，最大100条
//
// 返回:
//   - *__.GetSessionListResp: 包含会话列表的响应
//   - sessions: 会话列表，按更新时间倒序排列
//   - session_id: 会话唯一标识，用于继续对话
//   - title: 会话标题，便于用户识别
//   - created_at: 会话创建时间
//   - updated_at: 会话最后更新时间
//   - error: 错误信息，包含详细的错误描述
func (s *Server) GetSessionList(_ context.Context, in *__.GetSessionListReq) (*__.GetSessionListResp, error) {
	// 从数据库查询用户的会话列表
	// 按更新时间倒序排列，确保最新会话在前
	sessions, err := dao.GetSessionList(config.Ctx, in.GetUserId(), in.GetLimit())
	if err != nil {
		// 数据库查询失败，返回错误信息
		return nil, err
	}

	// 构建响应，将数据库记录转换为protobuf格式
	// 确保时间格式统一使用ISO8601标准
	resp := &__.GetSessionListResp{}
	for _, session := range sessions {
		resp.Sessions = append(resp.Sessions, &__.SessionItem{
			SessionId: session.SessionId,
			Title:     session.Title,
			CreatedAt: session.CreatedAt.Format(time.RFC3339), // 使用ISO8601格式，便于前端解析
			UpdatedAt: session.UpdatedAt.Format(time.RFC3339), // 使用ISO8601格式，便于前端解析
		})
	}
	return resp, nil
}
